import { Controller } from './Controller';
import { ConsoleBuilder } from './ConsoleBuilder';
import { ConsoleMiddleware, ConsolePlugin, Next } from '../plugins/Plugin';
import { compose, Composer } from '../utils/compose';
import { ConsoleContextHelper } from '../core/ConsoleContext';

export class ConsoleController<Props = {}, State = {}> extends Controller {
  protected builders: ConsoleBuilder<Props, State>[] = [];

  public create(command: string | string[]): ConsoleBuilder<Props, State> {
    const builder = new ConsoleBuilder(this.prefix, command);
    this.builders.push(builder);
    return builder;
  }

  public/*protected*/ getBuilders(): ConsoleBuilder[] {
    return this.builders;
  }

  public/*protected*/ createMiddleware(globalToLocal?: Composer): ConsoleMiddleware {
    const groupPlugins = this.getManager().getLocalPlugins().getPlugins();
    const builders = this.builders;
    const buildersLength = builders.length;

    return (ctx, next) => {
      const { command } = ctx;
      const middleware: Array<ConsolePlugin | ConsoleMiddleware> = [];

      for (let i = 0; i < buildersLength; ++i) {
        const builder = builders[i];
        if (builder.match(command)) {
          middleware.push(this.reset, ...builder.getPlugins());
        }
      }

      if (!middleware.length) {
        return next();
      }

      middleware.unshift(...groupPlugins);

      if (globalToLocal) {
        middleware.unshift(globalToLocal);
      }

      return compose(middleware)(ctx, next);
    };
  }

  protected reset(ctx: ConsoleContextHelper, next: Next) {
    ctx.commandMatched = true;
    // @ts-expect-error
    ctx.options = undefined;

    return next();
  }
}
